package cn.virens.components.spring;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import cn.virens.exception.APIException;

/**
 * <br>
 * (c) Copyright 2016 by <br>
 * 
 * @description : 以.json为后缀的请求，异常将以json形式返回 <br>
 * @file_name :CustomMappingExceptionResolver.java <br>
 * @system_name :ccqlk-security365-web <br>
 * @author :ccqlk-loioi <br>
 * @创建时间 :2016年11月21日 下午5:19:39
 */
public class VirensExceptionResolver extends SimpleMappingExceptionResolver implements InitializingBean {
	protected final Logger logger = LoggerFactory.getLogger(VirensExceptionResolver.class);

	private Map<Class<? extends Exception>, String> exceptionMessage = new HashMap<>();
	private Properties exceptionMappings = new Properties();

	private boolean isPrintError = true;

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
		if (isPrintError) logger.error(ex.getMessage(), ex);

		if (isJsonRequest(request)) {
			ModelAndView modelAndView = new ModelAndView();
			modelAndView.addObject("success", false);

			if (ex instanceof APIException) {
				modelAndView.addObject("code", ((APIException) ex).getCode());
				modelAndView.addObject("message", ((APIException) ex).getMessage());

				return modelAndView;
			} else {
				for (Entry<Class<? extends Exception>, String> entry : exceptionMessage.entrySet()) {
					if (entry.getKey().isAssignableFrom(ex.getClass())) {
						modelAndView.addObject("code", "unkown");
						modelAndView.addObject("message", entry.getValue());
						return modelAndView;
					}
				}
			}

			modelAndView.addObject("code", "unkown");
			modelAndView.addObject("message", ex.getMessage());
			return modelAndView;
		} else {
			return super.resolveException(request, response, handler, ex);
		}
	}

	public Map<Class<? extends Exception>, String> getExceptionMessage() {
		return exceptionMessage;
	}

	public void addExceptionMessage(Class<? extends Exception> exception, String message) {
		exceptionMessage.put(exception, message);
	}

	public void addExceptionMappings(Class<? extends Exception> exception, String view) {
		exceptionMappings.put(exception.getName(), view);

		setExceptionMappings(exceptionMappings);
	}

	public boolean isPrintError() {
		return isPrintError;
	}

	public void setPrintError(boolean isPrintError) {
		this.isPrintError = isPrintError;
	}

	private boolean isJsonRequest(HttpServletRequest request) {
		return request.getRequestURI().endsWith(".json");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		this.init();
	}

	public void init() {
		this.setExceptionMappings(exceptionMappings);
	}
}
